package com.engine.jucailinkq.attendance.workflow.action.askforleave;

import com.engine.jucailinkq.attendance.enums.AccountingUnitEnum;
import com.engine.jucailinkq.attendance.enums.CheckBoxEnum;
import com.engine.jucailinkq.attendance.workflow.enums.AskAndEvctionWayEnum;
import com.engine.jucailinkq.attendance.workflow.service.MakeUpClockInService;
import com.engine.jucailinkq.attendance.workflow.service.impl.MakeUpClockInServiceImpl;
import com.engine.common.util.*;
import com.engine.jucailinkq.common.util.CommonUtil;
import com.engine.jucailinkq.common.util.DateUtil;
import com.engine.jucailinkq.common.util.DbTools;
import com.engine.jucailinkq.common.util.Utils;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import weaver.general.Util;
import weaver.interfaces.workflow.action.Action;
import weaver.soa.workflow.request.RequestInfo;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
public class AskForLeaveWorkFlowSubmitAction implements Action {
    private MakeUpClockInService makeUpClockInService = ServiceUtil.getService(MakeUpClockInServiceImpl.class);

    @Override
    public String execute(RequestInfo requestInfo) {
        String requestid = requestInfo.getRequestid();
        int billid = requestInfo.getRequestManager().getBillid();
        log.info("billid : [{}]",billid);
        try {

            // 流程表单主表数据
            HashMap<String, String> mainTableData = CommonUtil.getMainTableInfo(requestInfo);
            log.info("mainTableData : [{}]", mainTableData);
            // 流程表单明细表1数据
            List<Map<String, String>> detailTableData = CommonUtil.getDetailTableInfo(requestInfo, 0);
            log.info("detailTableData : [{}]", detailTableData);

            String detail2TableName = requestInfo.getDetailTableInfo().getDetailTable()[1].getTableDBName();
            log.info("detail2TableName : [{}]", detail2TableName);
            //请假人员
            String qjry = mainTableData.get("qjry");
            //实际假期类型
            String jqlx = mainTableData.get("sjqjlx");
            //需要校验假期额度的假期类型
            List<String> checkAmountJqIdList = CommonUtil.getJqInfoWithAmount();
            //第一笔开始时间
            String firstStartDate = detailTableData.get(0).get("ksrq");

            List<Map<String, Object>> detailTable2 = Lists.newArrayList();


            /**
             * 补打卡日期是否关账
             */
            Map<String, Object> params = Maps.newHashMap();
            params.put("userId",qjry);
            params.put("submitDate", DateUtil.getCurrentDate());
            params.put("submitStr","ksrq");
            params.put("submitDataList",detailTableData);
            if (detailTableData == null || detailTableData.size() == 0){
                log.error("明细表没有数据！");
                requestInfo.getRequestManager().setMessageid("11111" + requestid + "22222");
                requestInfo.getRequestManager().setMessagecontent("明细表没有数据！");
                return Action.FAILURE_AND_CONTINUE;
            }
            Map<String,Object> dataMap = makeUpClockInService.getKqCycleTimeIntervalCmd(params);
            List<Map<String,Object>> closeList = (List<Map<String,Object>>)dataMap.get("closeList");
            List<String> nocycleList = (List<String>)dataMap.get("nocycleList");
            List<Map<String,Object>> dateList = (List<Map<String,Object>>)dataMap.get("dataList");

            boolean status = (boolean)dataMap.get("status");
            if (!status){
                log.error("该人员没有考勤周期");
                requestInfo.getRequestManager().setMessageid("11111" + requestid + "22222");
                requestInfo.getRequestManager().setMessagecontent("该人员没有考勤周期！");
                return Action.FAILURE_AND_CONTINUE;
            }
            if (closeList.size() > 0 || nocycleList.size() > 0){
                String message = "";
                if (nocycleList.size() > 0){
                    message = message +String.join(",",nocycleList)+"未找对对应的考勤周期；";
                }
                if (closeList.size() > 0){
                    List<String> list = closeList.stream().map(e->e.get("rq").toString()).collect(Collectors.toList());
                    message = message +String.join(",",list)+"对应的考勤周期的考勤周期已关账";
                }
                requestInfo.getRequestManager().setMessageid("11111" + requestid + "22222");
                requestInfo.getRequestManager().setMessagecontent(message);
                return Action.FAILURE_AND_CONTINUE;
            }
            /**
             * 请假时长是否满足“请假类型”中单次最小休时长，由假期额度表和流程主表获取对比数据
             */
            String jqedSql = "select eddw, dczskxsc, edbxdcxw from uf_jcl_kq_jqed where jb = ?";
            Map<String, Object> jqedInfo = DbTools.getSqlToMap(jqedSql, jqlx);
            //假期额度的额度单位，0-天、1-小时
            String eddw = Util.null2String(jqedInfo.get("eddw"));
            String eddwValue = "";
            //单次最小休时长
            String minDuration = Util.null2String(jqedInfo.get("dczskxsc"));
            //请假时长qjsc
            String qjsc = Util.null2String(mainTableData.get("qjsc"));
            //请假时长单位scdw，0-天、1-小时
            String scdw = Util.null2String(mainTableData.get("scdw"));
            String scdwValue = "";
            if (!"".equals(eddw) && !"".equals(minDuration)) {
                double minDurationValue = Double.parseDouble(minDuration);
                if (eddw.equals(AccountingUnitEnum.DAY.getKey())) {
                    minDurationValue = minDurationValue * 8;
                    eddwValue = AccountingUnitEnum.DAY.getValue();
                } else {
                    eddwValue = AccountingUnitEnum.HOUR.getValue();
                }
                double qjscValue = "".equals(qjsc) ? 0 : Double.parseDouble(qjsc);
                if (scdw.equals(AccountingUnitEnum.DAY.getKey())) {
                    qjscValue = qjscValue * 8;
                    scdwValue = AccountingUnitEnum.DAY.getValue();
                } else {
                    scdwValue = AccountingUnitEnum.HOUR.getValue();
                }

                if (Double.compare(minDurationValue, qjscValue) > 0) {
                    String message = "请假时长" + qjsc + eddwValue + "，不能小于单次最小休时长" + minDuration + scdwValue;
                    log.error(message);
                    requestInfo.getRequestManager().setMessageid("11111" + requestid + "22222");
                    requestInfo.getRequestManager().setMessagecontent(message);
                    return Action.FAILURE_AND_CONTINUE;
                }
            }
            /**
             * 请假是否满足“请假类型”中单条请假余额可休次数要求，由假期额度表、假期余额表、请假记录表和流程主表获取对比数据
             */
            //先获取假期额度规则中指定假别的可休次数
            String allowLeaveNumStr = Util.null2String(jqedInfo.get("edbxdcxw"));
            String sql = "select id,jqid,sxrq,ktsc,yxsc,wxsc,yqsxrq,ztsc from uf_jcl_kq_jqye where ygid=? and jqid=? and sxrq<=? and yqsxrq>=? order by sxrq";
            List<Map<String, Object>> holidayBalanceList = DbTools.getSqlToList(sql, qjry, jqlx, firstStartDate, firstStartDate);
            if (!allowLeaveNumStr.equals("") && holidayBalanceList.size() > 0) {
                //查询请假记录中，人员id+假期类别id情况下的结果，遍历每条主表数据下的明细数据中使用了哪些假期余额id
                sql = "select a.id,dt2.jqye from uf_jcl_kq_qjjl a left join uf_jcl_kq_qjjl_dt1 dt1 on dt1.mainid = a.id left join uf_jcl_kq_qjjl_dt2 dt2 on dt2.glmxid = dt1.glmxid " +
                        "where a.jqlx = " + jqlx + " and qjry = " + qjry + " and a.cxqj = 0 and dt1.cxqj = 0 and a.jlzt in (0, 1) and dt1.glmxid is not null";
                List<Map<String, Object>> leaveList = DbTools.getSqlToList(sql);
                Map<String, Integer> jqyeUseNumInfo = new HashMap<>();
                List<String> leaveUseList = new ArrayList<>();
                Integer useNum = 0;
                for (Map<String, Object> leaveItem : leaveList) {
                    String jqyeId = Util.null2String(leaveItem.get("jqye"));
                    if (!"".equals(jqyeId)) {
                        String leaveInfo = leaveItem.get("id").toString() + "_" + jqyeId;
                        if (leaveUseList.size() == 0) {
                            leaveUseList.add(leaveInfo);
                            jqyeUseNumInfo.put(jqyeId, 1);
                        } else if (!leaveUseList.contains(leaveInfo)) {
                            leaveUseList.add(leaveInfo);
                            useNum = jqyeUseNumInfo.get(jqyeId);
                            jqyeUseNumInfo.put(jqyeId, useNum == null ? 1 : ++useNum);
                        }
                    }
                }
                //筛选次数未使用完的假期余额
                holidayBalanceList = holidayBalanceList.stream().filter(f -> {
                    int beforeUseNum = jqyeUseNumInfo.get(f.get("id").toString()) == null ? 0 : jqyeUseNumInfo.get(f.get("id").toString());
                    return Integer.parseInt(allowLeaveNumStr) > beforeUseNum;
                }).collect(Collectors.toList());

                if (holidayBalanceList.size() == 0) {
                    String message = "本次使用的假期类型下的假期余额可休次数不足！";
                    log.error(message);
                    requestInfo.getRequestManager().setMessageid("11111" + requestid + "22222");
                    requestInfo.getRequestManager().setMessagecontent(message);
                    return Action.FAILURE_AND_CONTINUE;
                }

            }
            /**
             * 假期校验及入库
             */
//            String sql = "select id,jqid,sxrq,ktsc,yxsc,wxsc,yqsxrq,ztsc from uf_jcl_kq_jqye where ygid=? and jqid=? and sxrq<=? and yqsxrq>=? order by sxrq";
//            List<Map<String, Object>> holidayBalanceList = DbTools.getSqlToList(sql, qjry, jqlx, firstStartDate, firstStartDate);
            Map<String, Object> holidayBalanceMap = holidayBalanceList.stream().collect(Collectors.toMap(e -> e.get("id").toString(), e -> e));
            sql = "select id,mc,hsdw,hsl,jcbyxsyqjb,yxsydjb,qzsyyxjb  from uf_jcl_kq_kqxm  where id=?";
            Map<String, Object> holidayItem = DbTools.getSqlToMap(sql, jqlx);
            //当前假期类型需要校验剩余额度时则校验假期剩余额度，否则跳过校验
            if (checkAmountJqIdList.contains(jqlx)) {
                //假期核算单位
                String hsdw = Util.null2String(holidayItem.get("hsdw"));
                //请假方式
                String cxjqj = mainTableData.get("cxjqj");

                for (Map<String, String> detailData : detailTableData) {
                    String ksrq = Util.null2String(detailData.get("ksrq"));
                    String kssj = Util.null2String(detailData.get("kssj"));
                    String qtj = Util.null2String(detailData.get("qtj"));
                    String btj = Util.null2String(detailData.get("btj"));
                    //请假时间
                    double leaveDuration = 0;
                    if (qtj.equals(CheckBoxEnum.CHECKED.getKey())) {
                        leaveDuration = 1;
                    } else if (btj.equals(CheckBoxEnum.CHECKED.getKey())) {
                        leaveDuration = 0.5;
                    } else if (cxjqj.equals(AskAndEvctionWayEnum.TIME_INTERVAL.getKey()) || cxjqj.equals(AskAndEvctionWayEnum.HOUR.getKey())) {
                        leaveDuration = Double.valueOf(Util.null2String(detailData.get("qjsc")));
                    }
                    if (hsdw.equals(AccountingUnitEnum.HOUR.getKey()) && (cxjqj.equals(AskAndEvctionWayEnum.ALLDAY.getKey()) || cxjqj.equals(AskAndEvctionWayEnum.HALFDAY.getKey()))) {
                        leaveDuration = leaveDuration * 8;
                    }
                    log.info("leaveDuration : [{}]", leaveDuration);
                    List<Map<String, Object>> holidayBalancefilterList = Lists.newArrayList();
                    for (Map<String, Object> map : holidayBalanceList){
                        if (DateUtil.getTime(map.get("yqsxrq").toString()).compareTo(DateUtil.getTime(ksrq)) >= 0){
                            holidayBalancefilterList.add(map);
                        }
                    }
                    for (Map<String, Object> holidayBalance : holidayBalancefilterList) {
                        //额定未休时长
                        double wxsc = Util.null2String(holidayBalance.get("wxsc")).equals("") ? 0 : Double.valueOf(holidayBalance.get("wxsc").toString());
                        if (leaveDuration > 0) {
                            Map<String, Object> detail2Map = Maps.newHashMap();
                            detail2Map.put("glmxid", detailData.get("id"));
                            detail2Map.put("jqye", holidayBalance.get("id"));
                            detail2Map.put("mainid", mainTableData.get("id"));
                            detail2Map.put("glrq", detailData.get("ksrq"));
                            if (leaveDuration > wxsc) {
                                detail2Map.put("sysc", wxsc);
                                leaveDuration = Utils.subtract(leaveDuration, wxsc);
                                wxsc = 0;
                            } else {
                                detail2Map.put("sysc", leaveDuration);
                                wxsc = Utils.subtract(wxsc, leaveDuration);
                                leaveDuration = 0;
                            }
                            detailTable2.add(detail2Map);
                            holidayBalance.put("wxsc", wxsc);
                        }
                    }
                    if (leaveDuration > 0) {
                        //假期余额不足
//                        String message = ksrq + "对应的" + holidayItem.get("mc") + "假期余额不足！";
                        String message = holidayItem.get("mc") + "假期余额不足！";
                        log.error(message);
                        requestInfo.getRequestManager().setMessageid("11111" + requestid + "22222");
                        requestInfo.getRequestManager().setMessagecontent(message);
                        return Action.FAILURE_AND_CONTINUE;
                    }
                }
                log.info("detailTable2 : [{}]", detailTable2);

                //更新流程明细表2
                String delteSql = "delete from " + detail2TableName + " where mainid=?";
                DbTools.update(delteSql, billid);
                if (detailTable2.size() > 0 && !CommonUtil.insertBatch(detailTable2, detail2TableName)) {
                    //更新流程明细表2失败
                    String message = "更新流程明细表2失败";
                    log.error(message);
                    requestInfo.getRequestManager().setMessageid("11111" + requestid + "22222");
                    requestInfo.getRequestManager().setMessagecontent(message);
                    return Action.FAILURE_AND_CONTINUE;
                }

                //更新假期余额在途时长
                Map<String, Object> balanceMap = Maps.newHashMap();
                for (Map<String, Object> data : detailTable2) {
                    String jqye = Util.null2String(data.get("jqye"));
                    double sysc = Double.valueOf(data.get("sysc").toString());
                    double havedSysc = balanceMap.get(jqye) == null ? 0 : Double.valueOf(balanceMap.get(jqye).toString());
                    sysc = Utils.add(sysc, havedSysc);
                    balanceMap.put(jqye, sysc);
                }
                log.info("balanceMap : [{}]",balanceMap);
                for (Map.Entry<String, Object> entry : balanceMap.entrySet()) {
                    String id = entry.getKey();
                    double ztsc = Double.valueOf(entry.getValue().toString());
                    Map<String, Object> map = (Map<String, Object>) holidayBalanceMap.get(id);

                    double havedztsc = Util.null2String(map.get("ztsc")).equals("") ? 0 : Double.valueOf(map.get("ztsc").toString());
                    double havedwxsc = Util.null2String(map.get("wxsc")).equals("") ? 0 : Double.valueOf(map.get("wxsc").toString());

                    double updatedztsc = Utils.add(havedztsc, ztsc);
                   // double updatedwxsc = Utils.subtract(havedwxsc, ztsc);

                    String updateSql = "update uf_jcl_kq_jqye set wxsc=?,ztsc=? where id=?";
                    if (!DbTools.update(updateSql, havedwxsc, updatedztsc, id)) {
                        //更新假期余额失败
                        String message = "更新假期余额失败";
                        log.error(message);
                        requestInfo.getRequestManager().setMessageid("11111" + requestid + "22222");
                        requestInfo.getRequestManager().setMessagecontent(message);
                        return Action.FAILURE_AND_CONTINUE;
                    }
                }
            }

        }catch (Exception e){
            log.error("AskForLeaveWorkFlowSubmitAction error : [{}]",e);
            return Action.FAILURE_AND_CONTINUE;
        }

        return Action.SUCCESS;
    }
}
